import requests
import re
import time
from concurrent.futures import ThreadPoolExecutor

requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS = "TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-256-GCM-SHA384:ECDHE:!COMPLEMENTOFDEFAULT"
# 复制cookie到三引号中间，只需要替换这里
cookie = """
    你的cookie
    """
pool = ThreadPoolExecutor(max_workers=6)
post_header = {
    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36",
    "content-length": "130",
    "content-type": "application/x-www-form-urlencoded",
    "dnt": "1",
    "origin": "https://www.bilibili.com",
    "referer": "https://www.bilibili.com/",
    "sec-ch-ua": "\"Chromium\";v=\"94\", \"Google Chrome\";v=\"94\", \";Not A Brand\";v=\"99\"",
    "sec-fetch-mode": "cors",
    "sec-ch-ua-mobile": "?0",
    "sec-fetch-site": "same-site",
    "sec-fetch-dest": "empty",
    "sec-ch-ua-platform": "\"Windows\"",
    "cookie": '这里面不需要替换'
}
#
get_header = {
    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36",
    "cookie": '这里面不需要替换'
}

# 复制每日任务活动的task_id的值到这里
daily_task = {
    # 直播任务1
    "73af1865": False,
    "cec8a299": False,
    "bab2b65e": False,
    "185290e3": False,
    "b7e294d9": False,
    "6223f94c": False,
}
# 复制里程碑活动的task_id的值到这里，一定要确定好顺序，活动界面从上到下，从左到右开始计数
milepost_task = {
    # 3天
    "0f4416e8": False,
    # 5天
    "93617a9d": False,
    # 10天
    "c84a4da4": False,
    # 20天
    "3cba765a": False,
    # 30天
    "f800f808": False,
    # 40天
    "9976d3b4": False,
    # 新增舰长
    "03f40685": False
}

# 复制里程碑活动的task_id的值到这里，一定要确定好顺序，活动界面从上到下，从左到右开始计数
milepost_task_multi = [
    "0f4416e8",
    "93617a9d",
    "c84a4da4",
    "3cba765a",
    "f800f808",
    "9976d3b4",
    "03f40685"
]

reward_url = "https://api.bilibili.com/x/activity/mission/single_task"
receive_url = "https://api.bilibili.com/x/activity/mission/task/reward/receive"
csrf = ''

# 领取兑换码
def get_reward(url, body):
    response = requests.post(url, data=body, headers=post_header)
    response.encoding = 'utf-8'
    result = response.text
    cd_key_match = re.match(r'.*"cdkey_content":"(.*?)",', result)
    print("领取结果为： " + response.text)
    if cd_key_match:
        # cd_key_list.append(cd_key_match.group(1)+'\n')
        return True
    if result.__contains__("任务奖励已领取") or result.__contains__("来晚了"):
        return True
    return False


# 判断是否完成相应任务
def get_reward_item_id(url, body):
    t = time.time()
    if int(t) % 10 == 0:
        print("10显示一次：正在发起请求----" + url)
    response = requests.get(url, headers=get_header)
    response.encoding = 'utf-8'
    res = response.text
    print("查询结果为：" + res)
    macthObj = re.match(r'.*task_id":(.*?),"act_id":(.*?),"group_id":(.*?),.*receive_id":(.*?),', res)
    target = 0
    if macthObj:
        body["task_id"] = macthObj.group(1)
        body["act_id"] = macthObj.group(2)
        body["group_id"] = macthObj.group(3)
        body["receive_id"] = macthObj.group(4)
        target = macthObj.group(4)
    else:
        print("请确认你的网址等是否正确")
    return target


# 日常版本
def milepost_task_handler():
    body = {
        "csrf": csrf,
        "act_id": "74",
        "task_id": "159",
        "group_id": "1310",
        "receive_id": "255231",
        "receive_from": "missionLandingPage"
    }
    # 判断里程碑任务完成情况
    for i in milepost_task.keys():
        if milepost_task[i]:
            continue
        url = reward_url + "?csrf=" + body['csrf'] + "&id=" + i
        receive_id = get_reward_item_id(url, body)
        if receive_id == "0":
            milepost_task[i] = False
            continue
        milepost_task[i] = get_reward(receive_url, body)


def daily_task_handler():
    # 进行每日任务
    b_flag = 0
    body = {
        "csrf": csrf,
        "act_id": "74",
        "task_id": "159",
        "group_id": "1310",
        "receive_id": "255231",
        "receive_from": "missionLandingPage"
    }
    for i in daily_task.keys():
        if daily_task[i]:
            continue
        url = reward_url + "?csrf=" + body['csrf'] + "&id=" + i
        receive_id = get_reward_item_id(url, body)
        if receive_id == "0":
            daily_task[i] = False
            continue
        daily_task[i] = get_reward(receive_url, body)
        b_flag = b_flag + 1
        if b_flag >= 6:
            print("你已完成今日所有直播任务，开始尝试领取里程碑奖励")
            milepost_task_handler()
    print("本轮查询结束\n")


# 多线程端使用
def handler_task(index):
    body = {
        "csrf": csrf,
        "act_id": "74",
        "task_id": "159",
        "group_id": "1310",
        "receive_id": "255231",
        "receive_from": "missionLandingPage"
    }
    url = reward_url + "?csrf=" + body['csrf'] + "&id=" + milepost_task_multi[index]
    receive_id = get_reward_item_id(url, body)
    if receive_id != "0":
        print("本次要领取的物品编号为：" + milepost_task_multi[index])
        get_reward(receive_url, body)


# 批量领取兑换码，多线程版
def reward_multi_threads(collection):
    for i in collection:
        index = int(i) - 1
        pool.submit(handler_task, index)


# 循环领取奖励，多线程版
def cycle_reward_multi_threads():
    print("请输入要领取的里程碑奖励次序（活动界面从上到下，从左到右，从1开始）")
    print("多个任务以英文状态下的 , 隔开，例如 1,2,3")
    ids = input("请输入要领取的里程碑奖励次序（活动界面从上到下，从左到右，从1开始）\n")
    items = ids.split(",")
    a_flag = 0
    while True:
        a_flag = a_flag + 1
        # 开启多线程处理所有任务
        reward_multi_threads(items)
        if a_flag > 100:
            a_flag = 0
            time.sleep(2)


if __name__ == '__main__':
    print("领取的奖励请自行去活动页面查看，只抢里程碑的方式为多线程方式，容易造成内存溢出，请不要长时间运行(2小时以上)，内存大无所谓")
    macthObj = re.match(r'.*bili_jct=(.*?);', cookie.strip().replace(' ', ''))
    if macthObj:
        csrf = macthObj.group(1)
    post_header['cookie'] = cookie.strip().replace(' ', '')
    get_header['cookie'] = cookie.strip().replace(' ', '')
    print("1.领取日常任务，完成后领取里程碑奖励\n2.指定领取某些里程碑奖励，建议在每天即将刷新任务时开启程序")
    flag = input("请输入1或2\n")
    if flag == "1":
        while True:
            daily_task_handler()
            time.sleep(0.1)
    elif flag == "2":
        cycle_reward_multi_threads()
